package com.aruba.socketlibrary.protocol.SocketManager;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.aruba.socketlibrary.config.SerialportConfig;
import com.aruba.socketlibrary.protocol.SendManager.SendResponse;
import com.aruba.socketlibrary.protocol.SocketHelper;
import com.aruba.socketlibrary.protocol.handle.IDataHandleDelegate;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;


/**
 * Created by aruba on 2017/10/19.
 * 返回数据的处理，校验数据并去除头部和校验位等，只派发实际数据
 */

public abstract class SocketDataManager implements DataCallBack, Handler.Callback {
    private static final String tag = SocketDataManager.class.getSimpleName();

    protected byte nCommand;
    protected byte nSecondCommand;
    protected byte[] realData;
    protected IDataHandleDelegate dataHandleDelegate;
    protected Handler handler;
    protected Context context;
    protected int empty_count = 0;
    protected Runnable heatRunable = new Runnable() {
        @Override
        public void run() {
            handler.sendEmptyMessage(0);
        }
    };
    protected int heart_time = SerialportConfig.heart_time;

    private SocketHelper socketHelper;
    private String device_name;
    private int device_baudRate;

    public SocketDataManager(Context context) {
        this.context = context.getApplicationContext();
        dataHandleDelegate = getDataHandleDelegate();
    }

    public void open() {
        socketHelper = new SocketHelper(context, device_name, device_baudRate);
        socketHelper.setDataManger(this);
        try {
            socketHelper.open();
            //开启心跳
            handler = new Handler(Looper.myLooper(), this);
            handler.postDelayed(heatRunable, heart_time);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void callBack(byte[] readBuff, int size) {
        empty_count = 0;
        dataCallBack(readBuff, size);
    }

    public abstract void dataCallBack(byte[] readBuff, int size);

    @Override
    public void emptyCallBack() {
        empty_count++;
    }

    public boolean isConnect() {
        return socketHelper.isConnected();
    }

    public abstract IDataHandleDelegate getDataHandleDelegate();

    @Override
    public void bind(SocketHelper socketHelper) {
        dataHandleDelegate.setSerialHelper(socketHelper);
    }

    public boolean send(SendResponse sendResponse) {
        return dataHandleDelegate.send(sendResponse);
    }

    public void stop() {
        handler.removeCallbacks(heatRunable);
        dataHandleDelegate.stop();
    }

    @Override
    public boolean handleMessage(Message msg) {
        dataHandleDelegate.sendHeart();

        handler.postDelayed(heatRunable, heart_time);
        return false;
    }

    public void setHeart_time(int heart_time) {
        this.heart_time = heart_time;
    }

    public void setDevice_name(String device_name) {
        this.device_name = device_name;
    }

    public void setDevice_baudRate(int device_baudRate) {
        this.device_baudRate = device_baudRate;
    }

    public static class Builder {
        private Context mContext;
        private int heart_time = SerialportConfig.heart_time;
        private Class inflaterClass = SocketDataManager.class;
        private String device_name;
        private int device_baudRate;

        public Builder(Context mContext) {
            this.mContext = mContext.getApplicationContext();
        }

        /**
         * 心跳时间间隔
         *
         * @param heart_time
         * @return
         */
        public Builder heartTimeDely(int heart_time) {
            this.heart_time = heart_time;
            return this;
        }

        /**
         * 子类
         *
         * @param inflaterClass
         * @return
         */
        public Builder loadClass(Class<? extends SocketDataManager> inflaterClass) {
            this.inflaterClass = inflaterClass;
            return this;
        }

        /**
         * 串口名 波特率
         *
         * @param device_name
         * @param device_baudRate
         * @return
         */
        public Builder deviceConfig(String device_name, int device_baudRate) {
            this.device_name = device_name;
            this.device_baudRate = device_baudRate;
            return this;
        }

        public SocketDataManager build() {
            SocketDataManager socketDataManager = null;
            try {
                Class clazz = Class.forName(inflaterClass.getName());
                Constructor c = clazz.getConstructor(Context.class);
                socketDataManager = (SocketDataManager) c.newInstance(mContext);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

            socketDataManager.setHeart_time(heart_time);
            socketDataManager.setDevice_baudRate(device_baudRate);
            socketDataManager.setDevice_name(device_name);
            return socketDataManager;
        }
    }

}
